package boss.portal.util;

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.crypto.RSASSASigner;
import com.nimbusds.jose.crypto.RSASSAVerifier;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.gen.RSAKeyGenerator;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class RSaUtil {
    public static final  RSAKeyGenerator rsaKeyGenerator = new RSAKeyGenerator(2048);
    public static RSAKey rsaJWK;
    /**
     * 创建加密key
     */
    public static RSAKey getKey() throws JOSEException, JOSEException {
        if(rsaJWK == null){
            rsaJWK = rsaKeyGenerator.generate();
        }
        return rsaJWK;
    }

    /**
     * 过期时间5秒
     */
    private static final long EXPIRE_TIME = 1000 * 5;

    public static String buildToken(String account, String issuer, String subject) {
        try {
            /**
             * 1. 生成秘钥,秘钥是token的签名方持有，不可对外泄漏
             */
            System.out.println(getKey());
            RSASSASigner rsassaSigner = new RSASSASigner(getKey());

            /**
             * 2. 建立payload 载体
             */
            JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                    .subject(subject)
                   // .issuer("http://www.doiduoyi.com")
                    .issuer(issuer)
                   // .expirationTime(new Date(System.currentTimeMillis() + EXPIRE_TIME))
                    .claim("ACCOUNT",account)
                    .build();

            /**
             * 3. 建立签名
             */
            SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), claimsSet);
            signedJWT.sign(rsassaSigner);

            /**
             * 4. 生成token
             */
            String token = signedJWT.serialize();
            return token;

        } catch (JOSEException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static  Map<String,String> volidToken(String token) {
        try {
            SignedJWT jwt = SignedJWT.parse(token);
            System.out.println(getKey());
            //添加私密钥匙 进行解密
            RSASSAVerifier rsassaVerifier = new RSASSAVerifier(getKey().toRSAPublicKey());

            //校验是否有效
            if (!jwt.verify(rsassaVerifier)) {
                throw ResultException.of(-1, "Token 无效");
            }

            //校验超时
      /*      if (new Date().after(jwt.getJWTClaimsSet().getExpirationTime())) {
                throw ResultException.of(-2, "Token 已过期");
            }*/

            //获取载体中的数据
            Object account = jwt.getJWTClaimsSet().getClaim("ACCOUNT");
            Object subject = jwt.getJWTClaimsSet().getSubject();
            Object issuer = jwt.getJWTClaimsSet().getIssuer();


            //是否有openUid
            if (Objects.isNull(account)){
                throw ResultException.of(-3, "账号为空");
            }

            Map<String,String> resultMap = new HashMap<>();
            resultMap.put("account",String.valueOf(account));
            resultMap.put("subject",String.valueOf(subject));
            resultMap.put("issuer",String.valueOf(issuer));
            return resultMap;
        } catch (ParseException e) {
            e.printStackTrace();
        } catch (JOSEException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    public static Map<String, Object> getKeyJson() throws JOSEException {
        return new JWKSet(getKey()).toJSONObject();
    }


    public static void main(String[] args) throws JOSEException {
        System.out.println(getKey());
        String token = RSaUtil.buildToken("zyh","com","uu");

        System.out.println(getKey());
        Map m = RSaUtil.volidToken(token);

        System.out.println(token);
        System.out.println(m);
    }

}
